package e.odbo.data.util;

import com.openbravo.data.loader.serialize.DataWriteUtils;
import e.odbo.data.OdbOContent;
import e.odbo.data.model.*;

import java.util.Collection;
import java.util.List;
import java.util.Map;

public class DatabaseUtils {

    //resource
    public static void printBuildI18n(DataBase dataBase,String prefix,String temp){
        StringBuilder beanBuilder=new StringBuilder();
        buildI18nUseColumnComment(dataBase,beanBuilder,prefix,temp);
        System.out.print(beanBuilder.toString());
    }
    public static void printBuildI18nWithJava(DataBase dataBase,String prefix){
        printBuildI18n(dataBase,prefix,"%s = %s");
    }

    public static void printBuildI18nWithAndroid(DataBase table,String prefix){
        printBuildI18n(table,prefix,"<string name=\"%s\">%s</string>");
    }

    public static void printBuildI18nWithJavaScript(DataBase dataBase,String prefix){
        printBuildI18n(dataBase,prefix,"%s = '%s'");
    }

    public static void printBuildI18nJson(DataBase dataBase){
        StringBuilder beanBuilder=new StringBuilder();
        buildI18nJsonUseColumnComment(dataBase,beanBuilder,"%s : '%s'");
        System.out.print(beanBuilder.toString());
    }

    public static void buildI18nUseColumnComment(DataBase dataBase, StringBuilder i18nBuilder, String prefix, String tempString){
        if(prefix!=null&&!prefix.isEmpty())
            prefix=ClassUtils.getI18NString(prefix,dataBase.getName());
        else
            prefix=dataBase.getName();
        i18nBuilder.append(String.format(tempString, ClassUtils.getI18NString(prefix,"name"), dataBase.getName())+"\n");
        i18nBuilder.append(String.format(tempString, ClassUtils.getI18NString(prefix,"ver"), dataBase.getVersion())+"\n");
        for(Table table:dataBase.getTables())
            TableUtils.buildI18nUseColumnComment(table,i18nBuilder,prefix,tempString);
    }

    public static void buildI18nJsonUseColumnComment(DataBase dataBase, StringBuilder i18nBuilder,String tempString){
        i18nBuilder.append(dataBase.getName()+":{\n");
        i18nBuilder.append("\t"+String.format(tempString, "dataBase_ver", dataBase.getVersion())+",\n");
        List<Table> tables=dataBase.getTables();
        for(int i=0;i<tables.size();i++) {
            TableUtils.buildI18nJsonUseColumnComment(tables.get(i), i18nBuilder, tempString);
            if(i<tables.size()-1)
                i18nBuilder.append(",");
            i18nBuilder.append("\n");
        }
        i18nBuilder.append("}\n");
    }

    // Makedown
    public static void printMakedownDoc(DataBase dataBase){
        StringBuilder mdDocBuilder=new StringBuilder();
        buildMakedownDoc(dataBase,mdDocBuilder);
        System.out.print(mdDocBuilder.toString());
    }



    public static void buildMakedownDoc(DataBase dataBase, StringBuilder mdDocBuilder){
        List<Table> tables=dataBase.getTables();
        mdDocBuilder.append("# &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;"+ OdbOContent.MakeDownDOC_Title+"\n\n");
        mdDocBuilder.append("### 数据库名称："+dataBase.getName()+"( ver:"+dataBase.getVersion()+" )   \n\n");
        String subModel=dataBase.isSubModel()?"是":"否";
        mdDocBuilder.append("&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;共 : "+dataBase.getTables().size()+" 张表格, 插件数据库:"+subModel+"   \n\n\n");

        String tableComment=null;
        for(int i=0;i<tables.size();i++){
            tableComment=tables.get(i).getComment();
            String ref=TableUtils.buildTableName(tables.get(i));
            mdDocBuilder.append(String.format("%d. [%s](#%d.%s) \n\n ",i+1,StringUtils.fill(tableComment==null?tables.get(i).getName():tableComment,tables.get(i).getName(),50,'-'),i+1,ref));
        }
        mdDocBuilder.append("\n");

        if(dataBase.getMigrations().size()>0){
            mdDocBuilder.append("------\n");
            mdDocBuilder.append("### 历史版本:\n\n");
            for(Migration migration:dataBase.getMigrations()) {
                mdDocBuilder.append(String.format("+ [从: %s  到: %s](#从:%s到:%s)\n",migration.getOldVersion(),migration.getCurrentVersion(),migration.getOldVersion(),migration.getCurrentVersion()));
                if(null!=migration.getComment())
                    mdDocBuilder.append(">>>>>"+migration.getComment()+"\n");
            }
            mdDocBuilder.append("\n");
        }

        if(tables.size()<10)
            mdDocBuilder.append(OdbOContent.ICON);
        mdDocBuilder.append("\n------\n");
        Table table=null;
        for(int i=0;i<dataBase.getTables().size();i++) {
            table=tables.get(i);
            mdDocBuilder.append(String.format("## %d.%s",i+1,TableUtils.buildTableName(table)));
            TableUtils.buildTableStruct(table, mdDocBuilder);
        }

        buildMakedownDoc(dataBase.getAddData(),mdDocBuilder,true);

        buildMakedownDoc(dataBase.getMigrations(),mdDocBuilder);
    }

    public static void buildMakedownDoc(Collection<Migration> migrations, StringBuilder mdDocBuilder){
         if(migrations.size()>0) {
             mdDocBuilder.append("# 历史版本:\n\n");
             mdDocBuilder.append("------\n");
         }
         for(Migration migration:migrations) {
              buildMakedownDoc(migration, mdDocBuilder);
              mdDocBuilder.append("------\n");
          }
    }

    public static void buildMakedownDoc(Migration migration, StringBuilder mdDocBuilder){

        mdDocBuilder.append(String.format("## 从:%s到:%s\n\n",migration.getOldVersion(),migration.getCurrentVersion()));

        if(migration.getAddTable().size()>0) {
            mdDocBuilder.append(">>新增表:\n\n");
            for (Table table : migration.getAddTable()) {
                mdDocBuilder.append(String.format(">>> %s",TableUtils.buildTableName(table)));
                TableUtils.buildTableStruct(table, mdDocBuilder);
            }
            mdDocBuilder.append("\n");
        }

        if(migration.getRemoveTable().size()>0){
            mdDocBuilder.append(">>删除表:\n");
            for(String tableName:migration.getRemoveTable())
                mdDocBuilder.append("\t"+tableName);
            mdDocBuilder.append("\n");
        }

        if(migration.getAddData().size()>0) {
            mdDocBuilder.append((">>新增数据:\n\n"));
            buildMakedownDoc(migration.getAddData(),mdDocBuilder,true);
        }

        if(migration.getRemoveData().size()>0){
            mdDocBuilder.append((">>移除数据:\n\n"));
            buildMakedownDoc(migration.getRemoveData(),mdDocBuilder,false);
            mdDocBuilder.append("\n");
        }

        if(migration.getAddForeignKeys().size()>0){
            mdDocBuilder.append(">>新增外键:\n");
            for(TableForeignKey foreignKey:migration.getAddForeignKeys())
                TableUtils.buildTableStruct(foreignKey,mdDocBuilder);
            mdDocBuilder.append("\n");
        }

        if(migration.getRemoveForeignKeys().size()>0){
            mdDocBuilder.append(">>移除外键:\n");
            for(Map.Entry<String,String[]> foreignKey:migration.getRemoveForeignKeys().entrySet())
                mdDocBuilder.append(String.format("%s:%s(%s)\n",TableUtils.buildNameKey(foreignKey.getKey(),foreignKey.getValue()),foreignKey.getKey(),StringUtils.join(foreignKey.getValue(),',')));
            mdDocBuilder.append("\n");
        }

        if(migration.getAddColumn().size()>0){
            mdDocBuilder.append(">>表新增列:\n\n");
            StringBuilder memoBuilder=null;
            for(Map.Entry<String, Column[]> entry:migration.getAddColumn().entrySet()) {
                memoBuilder=new StringBuilder(TableUtils.getTableMemoString());
                mdDocBuilder.append(String.format(">>>  [%s](#%s) 新增列\n\n",entry.getKey(),entry.getKey()));
                Column[] columns=entry.getValue();
                TableUtils.buildTableStruct( columns, mdDocBuilder, memoBuilder);
                mdDocBuilder.append(memoBuilder);
                mdDocBuilder.append("\n-------\n");
            }
        }

        if(migration.getRemoveColumn().size()>0){
            mdDocBuilder.append(">>表移除列:\n");
            for(Map.Entry<String, String[]> entry:migration.getRemoveColumn().entrySet()) {
                mdDocBuilder.append(String.format(">>> 从表 [%s](#%s) 移除 列(*s)\n\n",entry.getKey(),entry.getKey(),StringUtils.join(entry.getValue(),',')));
                mdDocBuilder.append("\n-------\n");
            }
        }

        if(migration.getAlterColumn().size()>0){
            mdDocBuilder.append(">>表变更列:\n");
            StringBuilder memoBuilder=null;
            for(Map.Entry<String, Column[]> entry:migration.getAlterColumn().entrySet()) {
                memoBuilder=new StringBuilder(TableUtils.getTableMemoString());
                mdDocBuilder.append(String.format(">>> 表: [%s](#%s) 列变更为 :\n\n",entry.getKey(),entry.getKey()));
                Column[] columns=entry.getValue();
                TableUtils.buildTableStruct(columns, mdDocBuilder, memoBuilder);
                mdDocBuilder.append(memoBuilder);
                mdDocBuilder.append("\n-------\n");
            }
        }
        toTOP(mdDocBuilder);
    }

    public static void buildMakedownDoc(List<TableData> tableDataList, StringBuilder mdDocBuilder,boolean add){
         for(TableData tableData:tableDataList)
             buildMakedownDoc(tableData,mdDocBuilder,add);
    }

    public static void buildMakedownDoc(TableData tableData, StringBuilder mdDocBuilder,boolean add){
        String addStr=add?"新增":"移除";
        mdDocBuilder.append(String.format(">>>对表 : [%s](#%s) 进行 %s 数据 :\n",tableData.getTable(),tableData.getTable(),addStr));
        List<TableData.GenerateColumn> generateColumns=tableData.getGenerateColumns();
        List<Row> rows=tableData.getDatas();
        if(generateColumns.size()>0){
            mdDocBuilder.append("\t\t数据自动生成列 :\n");
            for(TableData.GenerateColumn generateColumn:generateColumns)
                mdDocBuilder.append((String.format("%s->%s\n",generateColumn.getColumn(),DataWriteUtils.getSQLValue(generateColumn.generator()))));
            mdDocBuilder.append("-------\n");
        }
        if(rows.size()>0){
            mdDocBuilder.append("\n");
            mdDocBuilder.append("| 序 ");
            for(String columnName:tableData.getColumn())
                mdDocBuilder.append("| "+columnName+" ");
            mdDocBuilder.append("\n");
            mdDocBuilder.append("| -  ");
            for(String columnName:tableData.getColumn())
                mdDocBuilder.append("| - ");
            mdDocBuilder.append("\n");
            for(int i=0;i<rows.size();i++){
                mdDocBuilder.append("| "+i+" ");
                for(Object value:rows.get(i).getValue()) {
                    mdDocBuilder.append(String.format("| %s" , value == null ? "-" : DataWriteUtils.getSQLValue(value)+" "));
                }
                mdDocBuilder.append("\n");
            }
            mdDocBuilder.append("\n-------\n");
        }
    }

    public static void toTOP(StringBuilder builder){
         builder.append(String.format("[<H6>返回目录</H6>](#%s) \n", OdbOContent.MakeDownDOC_Title));
    }
}
